package online

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkStopPublishReqData(data common.P2PStopPublishReqData) error {
	// Check if call ID is provided
	if data.CallId == "" {
		return errors.New("call_id is required in stop publish request")
	}

	// Check if user ID is provided
	if data.UserId == "" {
		return errors.New("user_id is required in stop publish request")
	}

	// Check if user exists
	if !s.userMgr.UserExists(data.UserId) {
		return errors.New("user client not found")
	}

	// Check if call exists
	if _, exists := s.callMgr.GetCall(data.CallId); !exists {
		return errors.New("call does not exist")
	}

	// Check if media exists for the user in the call
	if !s.callMgr.PublishMediaExists(data.CallId, data.UserId, data.Media) {
		return errors.New("media does not exist")
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendStopPublishResponse(rid string, code int, msg string,
	reqData common.P2PStopPublishReqData, connId string) {
	resMsg := common.Message{
		Cmd: common.P2P_STOP_PUBLISH_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: code,
			Msg:  msg,
			Data: common.P2PStopPublishResData{
				CallId: reqData.CallId,
				UserId: reqData.UserId,
				Media:  reqData.Media,
			},
		},
	}

	s.dispatcher.Dispatch(resMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleStopPublishReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleStopPublishReq")

	var reqData common.P2PStopPublishReqData
	if err := mapstructure.Decode(msg.Data, &reqData); err != nil {
		s.sendStopPublishResponse(msg.Rid, 1, err.Error(), reqData, connId)
		return nil
	}

	if err := s.checkStopPublishReqData(reqData); err != nil {
		s.sendStopPublishResponse(msg.Rid, 1, err.Error(), reqData, connId)
		return nil
	}

	if err := s.callMgr.RemovePublishMedia(reqData); err != nil {
		LOG(msg.Rid).WithError(err).Error("failed to remove publish media")
		s.sendStopPublishResponse(msg.Rid, 1, err.Error(), reqData, connId)
		return nil
	}

	s.sendStopPublishResponse(msg.Rid, 0, "success", reqData, connId)

	// Notify the peer user about the stop publish action
	peerUserId, err := s.callMgr.GetPeerUserId(reqData.CallId, reqData.UserId)
	if err != nil {
		LOG(msg.Rid).WithError(err).Error("failed to get peer user ID")
		return nil
	}

	peerUser := s.userMgr.GetUserByUserId(peerUserId)
	if peerUser == nil {
		LOG(msg.Rid).Error("peer user not found")
		return nil
	}

	// Dispatch the stop publish notification to the peer user
	stopPublishMsg := common.Message{
		Cmd: common.P2P_STOP_PUBLISH_NOTIFY,
		Rid: msg.Rid,
		Data: common.P2PStopPublishNotifyData{
			CallId: reqData.CallId,
			UserId: reqData.UserId,
			Media:  reqData.Media,
		},
	}
	s.dispatcher.Dispatch(stopPublishMsg, s.serviceInfo, common.AccessServiceInfo, peerUser.ConnId)

	return nil
}
